/* 该程序显示的是如何建立一个在输入Ctrl-C时返回主循环的SIGINT处理函数
 * 重要的是在调用siglongjmp前执行sigsetjmp创建一个返回点。
 * 调用sigaction应该出现在sigsetjmp前，这样它只会被调用一次
 * 为了防止信号处理函数在程序执行sigsetjmp前调用siglongjmp，程序中使用了jumpok
 * 信号处理函数在调用siglongjmp前检测这个标志
 */
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

static sigjmp_buf jmpbuf;
static volatile sig_atomic_t jumpok = 0;

/*AARGSUSED*/
static void chandler (int signo) {
    if (jumpok == 0) return ;
    siglongjmp(jmpbuf, 1);      // 使用siglongjmp函数跳转到返回点（这里为主函数）
}

int main() {
    struct sigaction act;

    act.sa_flags = 0;
    act.sa_handler = chandler;

    if ((sigemptyset(&act.sa_mask) == -1) || (sigaction(SIGINT, &act, NULL) == -1)) {
        perror("Failed to set up SIGINT handler");
        return 1;
    }

    fprintf(stderr, "This is process %ld\n", (long)getpid());
    if (sigsetjmp(jmpbuf, 1))       // sigsetjmp被直接激活会返回0，如果调用则会设置jumpok为1，并进入main循环
                                    // sigsetjmp通过调用siglongjmp激活时会返回val参数的值
        fprintf(stderr, "Returned to main loop due to ^C\n");
    
    jumpok = 1; // 防止信号处理函数在程序执行sigsetjmp前调用siglogjmp
    while(1);

    return 0;
}